Cache `Context::target_filenames`
authorAlex Crichton <alex@alexcrichton.com>
Fri, 2 Jun 2017 16:31:44 +0000 (09:31 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Mon, 5 Jun 2017 14:36:44 +0000 (07:36 -0700)
Relatively expensive to calculate, never changes, easy to add a cache!

src/cargo/ops/cargo_clean.rs
src/cargo/ops/cargo_rustc/context.rs
src/cargo/ops/cargo_rustc/fingerprint.rs
src/cargo/ops/cargo_rustc/mod.rs
src/cargo/ops/cargo_rustc/output_depinfo.rs

index 8a15bf19690e44fd04481fe323355507f72d4f81..19f518f8016f7c185a91c3de280357aa6121b58e 100644 (file)
@@ -83,10 +83,10 @@ pub fn clean(ws: &Workspace, opts: &CleanOptions) -> CargoResult<()> {
             continue
         }
 
-        for (src, link_dst, _) in cx.target_filenames(unit)? {
-            rm_rf(&src)?;
-            if let Some(dst) = link_dst {
-                rm_rf(&dst)?;
+        for &(ref src, ref link_dst, _) in cx.target_filenames(unit)?.iter() {
+            rm_rf(src)?;
+            if let Some(ref dst) = *link_dst {
+                rm_rf(dst)?;
             }
         }
     }
index 9842306bd3774d0b933cb544a68e8a6a5be6180b..1b1242f90385725c15c62d33594cbb7f959a2258 100644 (file)
@@ -53,6 +53,7 @@ pub struct Context<'a, 'cfg: 'a> {
     host_info: TargetInfo,
     profiles: &'a Profiles,
     incremental_enabled: bool,
+    target_filenames: HashMap<Unit<'a>, Arc<Vec<(PathBuf, Option<PathBuf>, bool)>>>,
 }
 
 #[derive(Clone, Default)]
@@ -133,6 +134,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
             used_in_plugin: HashSet::new(),
             incremental_enabled: incremental_enabled,
             jobserver: jobserver,
+            target_filenames: HashMap::new(),
         })
     }
 
@@ -544,8 +546,12 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
     /// filename: filename rustc compiles to. (Often has metadata suffix).
     /// link_dst: Optional file to link/copy the result to (without metadata suffix)
     /// linkable: Whether possible to link against file (eg it's a library)
-    pub fn target_filenames(&mut self, unit: &Unit)
-                            -> CargoResult<Vec<(PathBuf, Option<PathBuf>, bool)>> {
+    pub fn target_filenames(&mut self, unit: &Unit<'a>)
+                            -> CargoResult<Arc<Vec<(PathBuf, Option<PathBuf>, bool)>>> {
+        if let Some(cache) = self.target_filenames.get(unit) {
+            return Ok(cache.clone())
+        }
+
         let out_dir = self.out_dir(unit);
         let stem = self.file_stem(unit);
         let link_stem = self.link_stem(unit);
@@ -621,6 +627,9 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
                   unit.pkg, self.target_triple());
         }
         info!("Target filenames: {:?}", ret);
+
+        let ret = Arc::new(ret);
+        self.target_filenames.insert(*unit, ret.clone());
         Ok(ret)
     }
 
index 816bbe154b9865278705d0a94818ae01ac79f9d8..a3fc7ffe574ff6d1d44d9b3c2819611934901df7 100644 (file)
@@ -85,9 +85,9 @@ pub fn prepare_target<'a, 'cfg>(cx: &mut Context<'a, 'cfg>,
         missing_outputs = !root.join(unit.target.crate_name())
                                .join("index.html").exists();
     } else {
-        for (src, link_dst, _) in cx.target_filenames(unit)? {
+        for &(ref src, ref link_dst, _) in cx.target_filenames(unit)?.iter() {
             missing_outputs |= !src.exists();
-            if let Some(link_dst) = link_dst {
+            if let Some(ref link_dst) = *link_dst {
                 missing_outputs |= !link_dst.exists();
             }
         }
index 58e069a1376ef79bc8fb71f85be08408fea90e5d..e77740763024a1a37d0eb3feacc30359137fb2ee 100644 (file)
@@ -142,23 +142,23 @@ pub fn compile_targets<'a, 'cfg: 'a>(ws: &Workspace<'cfg>,
     queue.execute(&mut cx)?;
 
     for unit in units.iter() {
-        for (dst, link_dst, _linkable) in cx.target_filenames(unit)? {
-            let bindst = match link_dst {
-                Some(link_dst) => link_dst,
-                None => dst.clone(),
+        for &(ref dst, ref link_dst, _) in cx.target_filenames(unit)?.iter() {
+            let bindst = match *link_dst {
+                Some(ref link_dst) => link_dst,
+                None => dst,
             };
 
             if unit.profile.test {
                 cx.compilation.tests.push((unit.pkg.clone(),
                                            unit.target.kind().clone(),
                                            unit.target.name().to_string(),
-                                           dst));
+                                           dst.clone()));
             } else if unit.target.is_bin() || unit.target.is_example() {
-                cx.compilation.binaries.push(bindst);
+                cx.compilation.binaries.push(bindst.clone());
             } else if unit.target.is_lib() {
                 let pkgid = unit.pkg.package_id().clone();
                 cx.compilation.libraries.entry(pkgid).or_insert(HashSet::new())
-                  .insert((unit.target.clone(), dst));
+                  .insert((unit.target.clone(), dst.clone()));
             }
         }
 
@@ -179,8 +179,8 @@ pub fn compile_targets<'a, 'cfg: 'a>(ws: &Workspace<'cfg>,
             cx.compilation.libraries
                 .entry(unit.pkg.package_id().clone())
                 .or_insert(HashSet::new())
-                .extend(v.into_iter().map(|(f, _, _)| {
-                    (dep.target.clone(), f)
+                .extend(v.iter().map(|&(ref f, _, _)| {
+                    (dep.target.clone(), f.clone())
                 }));
         }
 
@@ -252,7 +252,9 @@ fn compile<'a, 'cfg: 'a>(cx: &mut Context<'a, 'cfg>,
     Ok(())
 }
 
-fn rustc(cx: &mut Context, unit: &Unit, exec: Arc<Executor>) -> CargoResult<Work> {
+fn rustc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>,
+                   unit: &Unit<'a>,
+                   exec: Arc<Executor>) -> CargoResult<Work> {
     let crate_types = unit.target.rustc_crate_types();
     let mut rustc = prepare_rustc(cx, crate_types, unit)?;
 
@@ -449,7 +451,9 @@ fn rustc(cx: &mut Context, unit: &Unit, exec: Arc<Executor>) -> CargoResult<Work
 
 /// Link the compiled target (often of form foo-{metadata_hash}) to the
 /// final target. This must happen during both "Fresh" and "Compile"
-fn link_targets(cx: &mut Context, unit: &Unit, fresh: bool) -> CargoResult<Work> {
+fn link_targets<'a, 'cfg>(cx: &mut Context<'a, 'cfg>,
+                          unit: &Unit<'a>,
+                          fresh: bool) -> CargoResult<Work> {
     let filenames = cx.target_filenames(unit)?;
     let package_id = unit.pkg.package_id().clone();
     let target = unit.target.clone();
@@ -572,9 +576,9 @@ fn filter_dynamic_search_path<'a, I>(paths :I, root_output: &PathBuf) -> Vec<Pat
     search_path
 }
 
-fn prepare_rustc(cx: &mut Context,
-                 crate_types: Vec<&str>,
-                 unit: &Unit) -> CargoResult<ProcessBuilder> {
+fn prepare_rustc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>,
+                           crate_types: Vec<&str>,
+                           unit: &Unit<'a>) -> CargoResult<ProcessBuilder> {
     let mut base = cx.compilation.rustc_process(unit.pkg)?;
     base.inherit_jobserver(&cx.jobserver);
     build_base_args(cx, &mut base, unit, &crate_types);
@@ -583,7 +587,8 @@ fn prepare_rustc(cx: &mut Context,
 }
 
 
-fn rustdoc(cx: &mut Context, unit: &Unit) -> CargoResult<Work> {
+fn rustdoc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>,
+                     unit: &Unit<'a>) -> CargoResult<Work> {
     let mut rustdoc = cx.compilation.rustdoc_process(unit.pkg)?;
     rustdoc.inherit_jobserver(&cx.jobserver);
     rustdoc.arg("--crate-name").arg(&unit.target.crate_name())
@@ -813,8 +818,9 @@ fn build_base_args(cx: &mut Context,
 }
 
 
-fn build_deps_args(cmd: &mut ProcessBuilder, cx: &mut Context, unit: &Unit)
-                   -> CargoResult<()> {
+fn build_deps_args<'a, 'cfg>(cmd: &mut ProcessBuilder,
+                             cx: &mut Context<'a, 'cfg>,
+                             unit: &Unit<'a>) -> CargoResult<()> {
     cmd.arg("-L").arg(&{
         let mut deps = OsString::from("dependency=");
         deps.push(cx.deps_dir(unit));
@@ -842,10 +848,11 @@ fn build_deps_args(cmd: &mut ProcessBuilder, cx: &mut Context, unit: &Unit)
 
     return Ok(());
 
-    fn link_to(cmd: &mut ProcessBuilder, cx: &mut Context, unit: &Unit)
-               -> CargoResult<()> {
-        for (dst, _link_dst, linkable) in cx.target_filenames(unit)? {
-            if !linkable {
+    fn link_to<'a, 'cfg>(cmd: &mut ProcessBuilder,
+                         cx: &mut Context<'a, 'cfg>,
+                         unit: &Unit<'a>) -> CargoResult<()> {
+        for &(ref dst, _, ref linkable) in cx.target_filenames(unit)?.iter() {
+            if !*linkable {
                 continue
             }
             let mut v = OsString::new();
index a7f67a043fb0910f84b8132b5244fac1ba1dff0f..60adf939e6e255236c4b11131fa5f5495b08fd76 100644 (file)
@@ -61,8 +61,8 @@ pub fn output_depinfo<'a, 'b>(context: &mut Context<'a, 'b>, unit: &Unit<'a>) ->
     let mut visited = HashSet::new();
     let success = add_deps_for_unit(&mut deps, context, unit, &mut visited).is_ok();
     let basedir = None; // TODO
-    for (_filename, link_dst, _linkable) in context.target_filenames(unit)? {
-        if let Some(link_dst) = link_dst {
+    for &(_, ref link_dst, _) in context.target_filenames(unit)?.iter() {
+        if let Some(ref link_dst) = *link_dst {
             let output_path = link_dst.with_extension("d");
             if success {
                 let mut outfile = BufWriter::new(File::create(output_path)?);